const path = require("path");

const {
  fileUploadError,
  publishGoodsError,
  invalidGoodsId,
  updateGoodsError,
  removeGoodsError,
  restoreGoodsError,
  findGoodsError,
} = require("../constant/error.type");
const { createGoods, updateGoods, removeGoods, restoreGoods, findGoods } = require("../service/goods.service");

class GoodsController {
  /**
   * 图片上传控制器
   * @param {*} ctx 请求上下文
   * @param {*} next 放行函数（可以不写，因为控制器一般是最后一个中间件了）
   */
  async upload(ctx, next) {
    try {
      console.log("ctx", ctx.request.files);
      const { file } = ctx.request.files;
      if (file) {
        ctx.body = {
          code: 0,
          message: "商品图片上传成功",
          result: {
            goods_img: path.basename(file.filepath), // path.basename(file.filepath)可以从文件目录字符串中获取到文件名
          },
        };
      } else {
        console.error("商品图片上传失败");
        return ctx.app.emit("error", fileUploadError, ctx);
      }
    } catch (error) {
      console.error("商品图片上传出错", error);
      ctx.app.emit("error", fileUploadError, ctx);
    }
  }
  /**
   * 创建商品信息
   * @param {*} ctx 请求上下文
   * @param {*} next 放行函数（可以不写，因为控制器一般是最后一个中间件了）
   */
  async create(ctx, next) {
    try {
      // 直接调用 service 的 createGoods 方法操作数据库
      const { createdAt, updatedAt, ...res } = await createGoods(ctx.request.body);
      ctx.body = {
        code: 0,
        message: "发布商品成功",
        result: res,
      };
    } catch (error) {
      console.error(error);
      // 不要把数据库操作的错误信息返回给前端,容易被黑客通过报错信息反推出表的结构和表信息，只需告诉前端这是服务器内部错误即可（要看错误信息直接在上面console查看打印日志即可）
      return ctx.app.emit("error", publishGoodsError, ctx);
    }
  }
  async update(ctx) {
    try {
      // 直接调用 service 的 updateGoods 方法操作数据库
      const res = await updateGoods(ctx.params.id, ctx.request.body);
      if (res) {
        ctx.body = {
          code: 0,
          message: "修改商品成功",
          result: "",
        };
      } else {
        return ctx.app.emit("error", invalidGoodsId, ctx);
      }
    } catch (error) {
      console.error(error);
      // 不要把数据库操作的错误信息返回给前端,容易被黑客通过报错信息反推出表的结构和表信息，只需告诉前端这是服务器内部错误即可（要看错误信息直接在上面console查看打印日志即可）
      return ctx.app.emit("error", updateGoodsError, ctx);
    }
  }
  async remove(ctx) {
    try {
      // 直接调用 service 的 removeGoods 方法操作数据库
      const res = await removeGoods(ctx.params.id);
      if (res) {
        ctx.body = {
          code: 0,
          message: "下架商品成功",
          result: "",
        };
      } else {
        return ctx.app.emit("error", invalidGoodsId, ctx);
      }
    } catch (error) {
      console.error(error);
      // 不要把数据库操作的错误信息返回给前端,容易被黑客通过报错信息反推出表的结构和表信息，只需告诉前端这是服务器内部错误即可（要看错误信息直接在上面console查看打印日志即可）
      return ctx.app.emit("error", removeGoodsError, ctx);
    }
  }
  async restore(ctx) {
    try {
      // 直接调用 service 的 restoreGoods 方法操作数据库
      const res = await restoreGoods(ctx.params.id);
      if (res) {
        ctx.body = {
          code: 0,
          message: "上架商品成功",
          result: "",
        };
      } else {
        return ctx.app.emit("error", invalidGoodsId, ctx);
      }
    } catch (error) {
      console.error(error);
      // 不要把数据库操作的错误信息返回给前端,容易被黑客通过报错信息反推出表的结构和表信息，只需告诉前端这是服务器内部错误即可（要看错误信息直接在上面console查看打印日志即可）
      return ctx.app.emit("error", restoreGoodsError, ctx);
    }
  }
  async findAll(ctx) {
    try {
      // HTTP 协议是基于文本的协议，所有通过 URL 传递的参数（包括 query 部分）都会被序列化为 纯文本字符串，所以在使用时要注意格式。
      const { pageNum = 1, pageSize = 10 } = ctx.request.query;
      // 直接调用 service 的 findGoods 方法操作数据库
      const res = await findGoods(pageNum, pageSize);
      if (res) {
        ctx.body = {
          code: 0,
          message: "获取商品列表成功",
          result: res,
        };
      } else {
        return ctx.app.emit("error", findGoodsError, ctx);
      }
    } catch (error) {
      console.error(error);
      // 不要把数据库操作的错误信息返回给前端,容易被黑客通过报错信息反推出表的结构和表信息，只需告诉前端这是服务器内部错误即可（要看错误信息直接在上面console查看打印日志即可）
      return ctx.app.emit("error", findGoodsError, ctx);
    }
  }
}

module.exports = new GoodsController();
